﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Windows.Forms;
using System.IO;

namespace simWaifu
{
    // One class which will handle all waifu data
    // (including filenames for data files etc)
    public static class Waifu
    {
        //
        // Data
        //

        public static Random rand = new Random();

        public static string waifuName = "Waifu";
        public static string anonName = "Anon-kun";
        public static string gender = "simWaifu";

        // types of moods (behaviour will vary depending on type)
        // welcome: always selected on application startup (todo: ignore if last mood was "sleeping")
        // chat: activated when chat mode is entered (todo: maybe forbid if current mood is "asleep")
        // special: list of user defined special moods which are excluded from random change (todo)
        // regular: all other moods, currently simWaifu will cycle randomly between those when idling
        public enum MoodType { welcome, chat, special, regular };

        public static MoodType curMoodType = MoodType.welcome;
        public static string curSubMood = "";

        // regular moods (only these will be used for random mood changes)
        public static List<Mood> regularMoods = new List<Mood>();

        // special moods
        public static Mood welcomeMood = new Mood(MoodType.welcome);
        public static Mood chatMood = new Mood(MoodType.chat);
        public static List<Mood> chatSubMoods = new List<Mood>();

        // list of special moods which are excluded from random
        // public static List<string> specialMoods = new List<string>)();
        // public static List<string> listMoods = new List<Mood>();
        //
        // handle special moods like sleep which are triggered by time of day
        //
        // string list of the mood names (since they are unique)?
        // or handle the moods in an own list and move them when they are selected to be special?
        // or store all in the main mood list and add a flag/enum/string to determing if they are special?
        // required data:
        // - time of day when mood is activated 
        // (maybe add some random offset so activation +/- xx minutes)
        // - day of week when mood is activated
        // (party on friday/saturday)
        // - day of month when mood is activated
        // (tell user to fetch welfare check from mailbox)
        // - month of year when mood is activated
        // (distinguish between seasons, maybe for background picture or showing beach scenes during summer)
        //  he ask
        // 

        public static int curRegularMood = -1;

        // supported image extensions
        static string[] imageExtensions = new string[]
        { "*.jpg", "*.bmp", "*.png", "*.tif", "*.gif" };

        // supported soundfile extensions
        static string[] soundExtensions = new string[]
        { "*.mp3", "*.MP3" };
        
        //
        // Methods
        //

        public static void Initialize()
        {
            DebugMessageHandler.WriteMsgLine("");
            DebugMessageHandler.WriteMsgLine("Waifu.Initialize() STARTING");
            DebugMessageHandler.WriteMsgLine("The WaifuDataFolder is set to: "
                + GetWaifuFolder());

            gender = Properties.Settings.Default.WaifuGender;
            waifuName = Properties.Settings.Default.WaifuName;

            InitializeWelcomeMood();
            InitializeChatMood();
            InitializeRegularMoods();
            
            DebugMessageHandler.WriteMsgLine("Number of regular moods: "
                + regularMoods.Count.ToString());

            DebugMessageHandler.WriteMsgLine("Waifu.Initialize() FINISHED");
            DebugMessageHandler.WriteMsgLine("");
        }

        public static string GetWaifuFolder()
        {
            // default: from settings
            string waifuFolder = Properties.Settings.Default.WaifuDataFolder;

            // does waifu folder have subfolder data?
            if(System.IO.Directory.Exists( Path.Combine(Properties.Settings.Default.WaifuFolder, "data")))
                waifuFolder = Path.Combine(Properties.Settings.Default.WaifuFolder, "data");
                
            return waifuFolder;
        }

        private static void InitializeWelcomeMood()
        {
            string waifuFolder = GetWaifuFolder();
            DebugMessageHandler.WriteMsgLine("InitializeWelcomeMood()");
            try
            {
                welcomeMood.Clear();
                welcomeMood.SetName("welcome");
                string folder = Path.Combine(waifuFolder, "welcome");

                if (System.IO.Directory.Exists(folder))
                {
                    InitializeMoodMessages(welcomeMood);
                    InitializeMoodPictures(welcomeMood);
                    InitializeMoodSounds(welcomeMood);
                }
                else
                {
                    DebugMessageHandler.WriteErrorLine("welcome mood folder does not exist!");
                }
            }
            catch (System.UnauthorizedAccessException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.UnauthorizedAccessException");
            }
            catch (System.IO.PathTooLongException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.PathTooLongException");
            }
            catch (System.IO.DirectoryNotFoundException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.DirectoryNotFoundException");
            }
            catch (System.IO.IOException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.IOException");
            }
        }

        private static void InitializeChatMood()
        {
            string waifuFolder = GetWaifuFolder();
            DebugMessageHandler.WriteMsgLine("InitializeChatMood()");
            try
            {
                chatMood.Clear();
                chatMood.SetName("chat");
                string folder = Path.Combine(waifuFolder, "chat");
                if (System.IO.Directory.Exists(folder))
                {
                    InitializeMoodMessages(chatMood);
                    InitializeMoodPictures(chatMood);
                    InitializeMoodSounds(chatMood);
                }
                else
                {
                    DebugMessageHandler.WriteErrorLine("chat mood folder does not exist!");
                }
            }
            catch (System.UnauthorizedAccessException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.UnauthorizedAccessException");
            }
            catch (System.IO.PathTooLongException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.PathTooLongException");
            }
            catch (System.IO.DirectoryNotFoundException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.DirectoryNotFoundException");
            }
            catch (System.IO.IOException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.IOException");
            }

            // now the sub moods
            InitializeChatSubMoods();
        }

        
        private static void InitializeChatSubMoods()
        {
            chatSubMoods.Clear();
            string moodFolder = Path.Combine( GetWaifuFolder(), chatMood.GetName());
            DebugMessageHandler.WriteMsgLine("InitializeChatSubMoods()");
            try
            {
                string[] dirs = System.IO.Directory.GetDirectories(moodFolder);
                for (int i = 0; i < dirs.Length; i++)
                {
                    string dir = dirs[i];
                    string mName = Path.Combine(chatMood.GetName(), dir.Substring(moodFolder.Length + 1));

                    //if (IsRegularMood(mName))
                    {
                        Mood m = new Mood(MoodType.chat);
                        DebugMessageHandler.WriteMsgLine("adding sub mood: " + mName);
                        m.SetName(mName);
                        chatSubMoods.Add(m);
                    }
                }
            }
            catch (System.UnauthorizedAccessException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.UnauthorizedAccessException");
            }
            catch (System.IO.PathTooLongException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.PathTooLongException");
            }
            catch (System.IO.DirectoryNotFoundException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.DirectoryNotFoundException");
            }
            catch (System.IO.IOException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.IOException");
            }
            if (chatSubMoods.Count > 0)
            {
                for (int m = 0; m < chatSubMoods.Count; m++)
                {
                    InitializeChatSubMood(chatSubMoods.ElementAt(m));
                }
            }
        }

        private static void InitializeChatSubMood(Mood m)
        {
            m.Clear();
            InitializeMoodMessages(m);
            InitializeMoodPictures(m);
            InitializeMoodSounds(m);
        }


        private static bool IsRegularMood(string name)
        {
            bool bRegular = true;
            if ((name.Equals("chat")) || (name.Equals("welcome")))
                bRegular = false;
            return bRegular;
        }

        private static void InitializeRegularMoods()
        {
            regularMoods.Clear();
            string waifuFolder = GetWaifuFolder();
            DebugMessageHandler.WriteMsgLine("InitializeRegularMoods()");
            try
            {
                string[] dirs = System.IO.Directory.GetDirectories(waifuFolder);
                for (int i = 0; i < dirs.Length; i++)
                {
                    string dir = dirs[i];
                    string mName = dir.Substring(waifuFolder.Length + 1);

                    if (IsRegularMood(mName))
                    {
                        Mood m = new Mood(MoodType.regular);
                        DebugMessageHandler.WriteMsgLine("adding mood: " + mName);
                        m.SetName(mName);
                        regularMoods.Add(m);
                    }
                }
            }
            catch (System.UnauthorizedAccessException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.UnauthorizedAccessException");
            }
            catch (System.IO.PathTooLongException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.PathTooLongException");
            }
            catch (System.IO.DirectoryNotFoundException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.DirectoryNotFoundException");
            }
            catch (System.IO.IOException)
            {
                DebugMessageHandler.WriteError("InitializeMoods(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.IOException");
            }
            if (regularMoods.Count > 0)
            {
                for (int m = 0; m < regularMoods.Count; m++)
                {
                    InitializeRegularMood(regularMoods.ElementAt(m));
                }
            }
        }

        private static void InitializeRegularMood(Mood m)
        {
            m.Clear();
            InitializeMoodMessages(m);
            InitializeMoodPictures(m);
            InitializeMoodSounds(m);
        }

        private static void InitializeMoodMessages(Mood m)
        {
            string moodMsgName = Path.Combine(
                GetWaifuFolder(),
                m.GetName(),
                "messages.txt");
            DebugMessageHandler.WriteMsgLine("mood Message File: " + moodMsgName);
            try
            {
                if (System.IO.File.Exists(moodMsgName))
                {
                    StreamReader reader = new System.IO.StreamReader(moodMsgName);
                    while (!reader.EndOfStream)
                    {
                        string msg = reader.ReadLine();
                        if (msg.Length > 0)
                            m.AddMessage(msg);
                        else
                            DebugMessageHandler.WriteErrorLine("InitializeMoodMessages(): empty message!");
                    }
                    reader.Close();
                }
                else
                {
                    DebugMessageHandler.WriteMsgLine("No messages.txt in folder: " + moodMsgName);
                }
            }
            catch (System.UnauthorizedAccessException)
            {
                DebugMessageHandler.WriteError("InitializeMoodMessages(): ");
                DebugMessageHandler.WriteErrorLine("System.UnauthorizedAccessException");
            }
            catch (System.IO.PathTooLongException)
            {
                DebugMessageHandler.WriteError("InitializeMoodMessages(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.PathTooLongException");
            }
            catch (System.IO.DirectoryNotFoundException)
            {
                DebugMessageHandler.WriteError("InitializeMoodMessages(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.DirectoryNotFoundException");
            }
            catch (System.IO.IOException)
            {
                DebugMessageHandler.WriteError("InitializeMoodMessages(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.IOException");
            }
        }

        private static void InitializeMoodPictures(Mood m, string moodFolder, string fileExtension)
        {
            try
            {
                string[] files;              
                files = System.IO.Directory.GetFiles(moodFolder, fileExtension);
                for (int f=0; f<files.Length;f++)
                {
                    string file=files[f].Substring(moodFolder.Length+1);
                    m.AddPicture(file);
                    //DebugMessageHandler.WriteMsgLine("added mood picture: " + file);
                }
            }
            catch (System.IO.PathTooLongException)
            {
                DebugMessageHandler.WriteErrorLine("System.PathTooLongException");
            }         
            catch (System.IO.DirectoryNotFoundException)
            {
                DebugMessageHandler.WriteErrorLine("System.DirectoryNotFoundException");
            }
            catch (System.IO.IOException)
            {
                DebugMessageHandler.WriteErrorLine("System.IO.IOException");
            }
            catch (System.UnauthorizedAccessException)
            {
                DebugMessageHandler.WriteErrorLine("System.UnauthorizedAccessException");
            }
        }

        private static void InitializeMoodPictures(Mood m)
        {
            string moodFolder = Path.Combine(GetWaifuFolder(), m.GetName());
            if(System.IO.Directory.Exists(moodFolder))
            {
                DebugMessageHandler.WriteMsgLine("scanning mood folder for pictures: " + moodFolder);
                for (int i = 0; i < imageExtensions.Length; i++)
                    InitializeMoodPictures(m, moodFolder, imageExtensions[i]);
            }
            else
            {
                DebugMessageHandler.WriteErrorLine("mood folder does not exist: " + moodFolder);
            }
        }

        private static void InitializeMoodSounds(Mood m, string moodFolder, string fileExtension)
        {
            try
            {
                string[] files;
                files = System.IO.Directory.GetFiles(moodFolder, fileExtension);
                for (int f = 0; f < files.Length; f++)
                {
                    string file = files[f].Substring(moodFolder.Length + 1);
                    m.AddSound(file);
                    //DebugMessageHandler.WriteMsgLine("added mood sound: " + file);
                }
            }
            catch (System.IO.PathTooLongException)
            {
                DebugMessageHandler.WriteError("InitializeMoodSounds(): ");
                DebugMessageHandler.WriteErrorLine("System.PathTooLongException");
            }
            catch (System.IO.DirectoryNotFoundException)
            {
                DebugMessageHandler.WriteError("InitializeMoodSounds(): ");
                DebugMessageHandler.WriteErrorLine("System.DirectoryNotFoundException");
            }
            catch (System.IO.IOException)
            {
                DebugMessageHandler.WriteError("InitializeMoodSounds(): ");
                DebugMessageHandler.WriteErrorLine("System.IO.IOException");
            }
            catch (System.UnauthorizedAccessException)
            {
                DebugMessageHandler.WriteError("InitializeMoodSounds(): ");
                DebugMessageHandler.WriteErrorLine("System.UnauthorizedAccessException");
            }
        }

        private static void InitializeMoodSounds(Mood m)
        {
            string moodFolder = Path.Combine(GetWaifuFolder(), m.GetName());
           
            if(System.IO.Directory.Exists(moodFolder))
            {
                DebugMessageHandler.WriteMsgLine("scanning mood folder for soundfiles: " + moodFolder);
                for (int i = 0; i < soundExtensions.Length; i++)
                    InitializeMoodSounds(m, moodFolder, soundExtensions[i]);
            }
            else
            {
                DebugMessageHandler.WriteErrorLine("mood folder does not exist: " + moodFolder);
            }
        }

        public static void ChangeRegularMood(int newMood)
        {
            DebugMessageHandler.WriteMsgLine("Mood change (specific) requested: " + newMood.ToString());
            if (newMood < regularMoods.Count)
                curRegularMood = newMood;
            else
                DebugMessageHandler.WriteMsgLine("That mood does not exist! " + newMood.ToString());
        }

        // select a random new regular mood
        // (special moods like welcome, chat, sleep, ... are ignored)
        public static void ChangeRegularMoodRandom()
        {
            if (regularMoods.Count > 0)
            {
                // need at least two moods to change randomly
                if (regularMoods.Count == 1)
                {
                    curRegularMood = 0;
                }
                else
                {
                    int m = curRegularMood;
                    while (m == curRegularMood)
                        m = rand.Next(regularMoods.Count);
                    curRegularMood = m;
                }
            }
            else 
            {
                DebugMessageHandler.WriteMsgLine("ChangeMoodRandom(): no moods available!");
            }
        }

        public static string ChangeMoodMessage()
        {
            string msg = "";
            switch (curMoodType)
            {
                case MoodType.welcome:
                    msg = welcomeMood.ChangeMessage();
                    break;
                case MoodType.chat:
                    DebugMessageHandler.WriteErrorLine("ChangeMoodMessage should not be called in chat mood");
                    break;
                case MoodType.special:
                    // special moods not implemented yet
                    break;
                case MoodType.regular:
                    if ((curRegularMood >= 0) && (regularMoods.Count > 0))
                    {
                        msg = regularMoods.ElementAt(curRegularMood).ChangeMessage();
                    }
                    break;
                default:
                    DebugMessageHandler.WriteErrorLine("ChangeMoodMesage: unknown mood type");
                    break;
            }
            return msg;
        }

        public static string ChangeMoodSound()
        {
            string snd = "";
            switch (curMoodType)
            {
                case MoodType.welcome:
                    snd = welcomeMood.ChangeSound();
                    break;
                case MoodType.chat:
                    DebugMessageHandler.WriteErrorLine("ChangeMoodSound should not be called in chat mood");
                    break;
                case MoodType.special:
                    // special moods not implemented yet
                    break;
                case MoodType.regular:
                    if ((curRegularMood >= 0) && (regularMoods.Count > 0))
                    {
                        snd = regularMoods.ElementAt(curRegularMood).ChangeSound();
                    }
                    break;
                default:
                    DebugMessageHandler.WriteErrorLine("ChangeMoodSound: unknown mood type");
                    break;
            }
            return snd;
        }

        public static string ChangeMoodPicture()
        {
            string pic = "";
            switch (curMoodType)
            {
                case MoodType.welcome:
                    pic = welcomeMood.ChangePicture();
                    break;
                case MoodType.chat:
                    if (curSubMood.Equals(""))
                    {
                        pic = chatMood.ChangePicture();
                    }
                    else
                    {
                        // set picture from main mood in case no sub mood pic is found
                        pic = chatMood.ChangePicture();

                        // check if sub mood exists, write error message if it doesn´t
                        // get picture from sub mood
                        // pic = 
                        DebugMessageHandler.WriteMsgLine("submood = " + curSubMood);
                        if (chatSubMoods.Count > 0)
                        {
                            string searchFor = Path.Combine(chatMood.GetName(), curSubMood);                                
                            bool bFound = false;
                            // todo: convert into while loop to bail out if pic was found
                            for(int i=0; i<chatSubMoods.Count; i++)
                            {
                                if (chatSubMoods[i].GetName().Equals(searchFor))
                                {
                                    string newpic = chatSubMoods[i].ChangePicture();
                                    if (newpic.Length>0)
                                        pic = newpic;
                                    bFound = true;
                                }
                            }
                            if (!bFound)
                                DebugMessageHandler.WriteMsgLine("submood not found: " + curSubMood);
                        }
                        else
                        {
                            DebugMessageHandler.WriteMsgLine("no submoods available");
                        }
                    }
                    break;
                case MoodType.special:
                    // special moods not implemented yet
                    break;
                case MoodType.regular:
                    if ((curRegularMood >= 0) && (regularMoods.Count > 0))
                    {
                        pic = regularMoods.ElementAt(curRegularMood).ChangePicture();
                    }
                    break;
                default:
                    DebugMessageHandler.WriteErrorLine("ChangeMoodSound: unknown mood type");
                    break;
            }
            return pic;        
        }

        public static string GetRegularMoodName(int m)
        {
            string name = "";
            if (m == -1)
                name = "no mood";
            else
            {
                if (m >= regularMoods.Count)
                    return "invalid mood number!";
                name = regularMoods.ElementAt(m).GetName();
            }
            return name;
        }

        public static string GetCurrentMood()
        {
            string moodName = "";
            switch (curMoodType)
            {
                case MoodType.welcome:
                    moodName = "welcome";
                    break;
                case MoodType.chat:
                    moodName = "chat";
                    break;
                case MoodType.special:
                    // special moods not implemented yet
                    moodName = "special";
                    break;
                case MoodType.regular:
                    moodName = GetRegularMoodName(curRegularMood);
                    break;
                default:
                    DebugMessageHandler.WriteErrorLine("GetCurrentMood: unknown mood type");
                    break;
            }
            return moodName;
        }    

        static public void SetMoodType(Waifu.MoodType newMood)
        {
            curMoodType = newMood;
        }
    }
}
